﻿using aspNetCURD.Dtos;
using aspNetCURD.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Newtonsoft.Json;
using Microsoft.AspNetCore.JsonPatch;
using AutoMapper;
using aspNetCURD.Database;
using Microsoft.EntityFrameworkCore;
using aspNetCURD.Models;

namespace aspNetCURD.Controllers
{
    [Route("auth")]
    [ApiController]
    public class AuthenticateController : ControllerBase
    {
        private readonly IConfiguration _configuration;
        private readonly IStudentRepository _studentRepository;
        private readonly AppDbContext _context;
        public AuthenticateController(IConfiguration configuration, IStudentRepository studentRepository, AppDbContext context)
        {
            _configuration = configuration;
            _studentRepository = studentRepository;
            _context = context;
        }
        /// <summary>
        /// 登录验证
        /// </summary>
        /// <param name="loginDto"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("login")]
        public IActionResult Login([FromBody] LoginDto loginDto)
        {
            if (loginDto.sno == null || loginDto.password == null)
            {
                return BadRequest("账号或密码错误");
            }
            // 1、验证用户名和密码
            var studentRepository = _studentRepository.GetStudent(loginDto.sno);
            if (studentRepository == null)
            {
                return BadRequest("账号不对");
            }
            if (!string.IsNullOrEmpty(studentRepository.password))
            {
                if (studentRepository.password.Trim() != loginDto.password)
                {
                    return BadRequest("登录密码错误");
                }
            }
            else
            {
                return BadRequest("该用户还未注册");
            }

            // 2、创建 jwt   jwt = header + payload + signiure
            // header 定义了 token的编码算法
            var signinAlgorithm = SecurityAlgorithms.HmacSha256;
            // payload 主体数据，可自定义

            // 在 claims中注明用户的身份和权限
            var claims = new[]
            {
                // jwt中 id 的专有名词：sub
                new Claim(Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames.Sub,loginDto.sno)
            };
            // signiure 数字签名（私钥）,放置在配置文件中。 密钥的长度至少为16个字符，不然会报错
            var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);
            // 使用非对称加密算法进行加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            // 数字签名
            var signingCreadentials = new SigningCredentials(signingKey, signinAlgorithm);

            //创建 token
            var token = new JwtSecurityToken(
                issuer: _configuration["Authentication:Issuer"],
                audience: _configuration["Authentication:Audience"],
                claims,
                notBefore: DateTime.UtcNow,
                expires: DateTime.UtcNow.AddDays(1),
                signingCreadentials
            );

            var tokenstr = new JwtSecurityTokenHandler().WriteToken(token);
            // 3、返回 200 ok 、jwt
            return Ok(tokenstr);
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="registerDto"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPatch]
        public IActionResult Register([FromBody] RegisterDto registerDto)
        {
            if (_studentRepository.StudentEmpty(registerDto.sno))
            {
                return BadRequest("不存在该学生，不能注册此账号");
            }
            var studentRepository = _studentRepository.GetStudent(registerDto.sno);
            studentRepository.password = registerDto.password;
            _context.Entry(studentRepository).State = EntityState.Modified;
            _context.SaveChanges();
            return Ok("注册成功");
        }
    }
}
